package com.homwee.serialportinspection;

import static com.homwee.serialportinspection.serialport.VinsmartCommand.setFactoryMode;

import android.app.ActivityManager;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.net.wifi.ScanResult;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.provider.Settings;
import android.util.Log;
import com.homwee.factory.R;

import com.homwee.serialportinspection.model.Controller;
import com.homwee.serialportinspection.model.RequestHandler;
import com.homwee.serialportinspection.model.Types;
import com.homwee.serialportinspection.serialport.MtkSerialPort;
import com.homwee.serialportinspection.serialport.SerialPortController;
import com.homwee.serialportinspection.serialport.VinsmartCommand;
import com.homwee.serialportinspection.tv.Antv;
import com.homwee.serialportinspection.tv.Tv;
import com.homwee.serialportinspection.tv.TvRequstHandler;

import java.lang.ref.WeakReference;
import java.util.List;

public class InspectionService extends Service {
    private static final String TAG = "InspectionService";

    private static final int MSG_REQUEST = 0;
    private static final int MINUTES_IN_TWO_HOURS = 120;
    private static final String CHANNEL_ID = "SerialPortInspectionService";
    private static final String ACTION_SCREEN_ON = "android.intent.action.SCREEN_ON";
    private static final String ACTION_SCREEN_OFF = "android.intent.action.SCREEN_OFF";
    private boolean mIsStarted  = false;
    private Controller mController;
    private Tv mTv;
    private RequestHandler mRequestHandler;
    private MsgHandler mMsgHandler;
    private Context context;
    private MtkSerialPort mMtkSerialPort;

    /**
     * false:unregister receiver
     * true:register
     */
    private boolean screenOnReceiverFlag = false;

    private Controller.Listener mControllerListener = new Controller.Listener() {
        @Override
        public boolean onRequest(Controller controller, Message request) {
            return handleRequest(request);
        }
    };

    private Tv.ResultListener mResultListener = new Tv.ResultListener() {
        @Override
        public void onWifiScanResult(List<ScanResult> results) {
            // Do nothing because VS_COMMAND will send PARAM_WIFI_CMP_RSSI WIFI command
        }

        @Override
        public void onBtDiscoveryResult(BluetoothDevice bt) {
            Message response = Message.obtain();
            response.what = Types.Request.GET_BT_DISCOVERIED_DEV.ordinal();
            response.obj = bt;
            mController.sendResponse(response);
        }
    };

    private static class MsgHandler extends Handler {
        private WeakReference<InspectionService> mService;

        MsgHandler(InspectionService service) {
            mService = new WeakReference<>(service);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_REQUEST:
                    Message request = (Message) msg.obj;
                    InspectionService service = mService.get();
                    if (service != null) {
                        service.handleRequest(request);
                    } else {
                        Log.e(TAG, "service is null");
                    }
                default:
                    super.handleMessage(msg);
            }
        }
    }

    @Override
    public void onCreate() {
        super.onCreate();

        context = getApplicationContext();

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel(
                    CHANNEL_ID, "InspectionService", NotificationManager.IMPORTANCE_MIN);
            channel.enableLights(false);
            channel.setLightColor(Color.RED);
            channel.setShowBadge(false);
            channel.setDescription("InspectionService");
            channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);

            NotificationManager manager =
                    (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
            manager.createNotificationChannel(channel);
            Notification notification = new Notification.Builder(this)
                    .setChannelId(CHANNEL_ID)
                    .setContentTitle("UartSrv")
                    .setContentText("Running")
                    .setWhen(System.currentTimeMillis())
                    .setSmallIcon(R.drawable.ic_launcher)
                    .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher))
                    .build();
            startForeground(1, notification);

            //Start LiveTv
            Intent liveTvIntent = new Intent();
            liveTvIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            liveTvIntent.setComponent(
                new ComponentName(
                    "com.mediatek.wwtv.tvcenter", "com.mediatek.wwtv.tvcenter.nav.TurnkeyUiMainActivity"));
            try {
                startActivity(liveTvIntent);
            } catch (RuntimeException e) {
                Log.d(TAG, "Start LiveTV Fail");
            }
            Log.d(TAG, "onCreate: StartService start");

            if (false == screenOnReceiverFlag) {
                /* Register the SCREEN ON broadcast. */
                IntentFilter mScreenOnFilter = new IntentFilter(ACTION_SCREEN_ON);
                InspectionService.this.registerReceiver(mScreenReceiver, mScreenOnFilter);
                screenOnReceiverFlag = true;
            }

            /* Switch On */
            SetAutotestSwitch(true);
            Log.d(TAG, "onCreate: StartService end");
        }
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        super.onStartCommand(intent, flags, startId);
        Log.d(TAG, "onStartCommand start");
        if (!mIsStarted) {
            init(intent);
        }
        Log.d(TAG, "onStartCommand end");

        return START_STICKY;
    }

    @Override
    public IBinder onBind(Intent intent) {
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public void onDestroy() {
        uninit();
        Log.d(TAG, "onDestroy");
    }


    /**
     * function.
     */
    private boolean handleRequest(Message request) {
        Log.d(TAG, "handleRequest in");
        Message response = mRequestHandler.handle(request);
        return mController.sendResponse(response);
    }

    private void init(Intent intent) {
        mMtkSerialPort = new MtkSerialPort();
        mController = new SerialPortController(mMtkSerialPort, new VinsmartCommand());
        mTv = new Antv(this);
        mRequestHandler = new TvRequstHandler(mTv);
        mMsgHandler = new MsgHandler(this);
        mController.registerListener(mControllerListener);
        mTv.registerResultListener(mResultListener);

        // 2 hour
        mTv.setScreenSaverTime(MINUTES_IN_TWO_HOURS);
        // never
        mTv.setNoOperSleepTime(-1);
        // off
        mTv.setNoSignalPowerOffTime(0);
        mIsStarted = true;
        mController.start();
        //Init flag
        setFactoryMode(Types.FactoryMode.STATE_INIT.ordinal());

        SetAutotestSwitch(true);
    }

    private void uninit() {
        super.onDestroy();
        SetAutotestSwitch(false);
        /**
         * Unregister receivers
         */
        if (true == screenOnReceiverFlag) {
            unregisterReceiver(mScreenReceiver);
            screenOnReceiverFlag = false;
        }
        mTv.UninitAntv();
        mIsStarted = false;
        mTv.unregisterResultListener(mResultListener);
        mTv.hideCtValue();
        mTv.hideUI();
        mController.unregisterListener(mControllerListener);
        mController.stop();
        stopForeground(true);

        /**
         * reset flag;
         */
        setFactoryMode(Types.FactoryMode.STATE_INIT.ordinal());

        SetAutotestSwitch(false);
    }

    public static boolean isRunService(Context context, String serviceName) {
        ActivityManager manager = (ActivityManager) context.getSystemService(ACTIVITY_SERVICE);
        for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
            if (serviceName.equals(service.service.getClassName())) {
                return true;
            }
        }
        return false;
    }

    /**
     * @param:false - auto test is switch off
     * @param:true - auto test is swich on
     */
    public void SetAutotestSwitch(boolean onOff) {
	    /*
        if (true == onOff) {
            Settings.Global.putString(getContentResolver(), "auto_test", "On");
        } else {
            Settings.Global.putString(getContentResolver(), "auto_test", "Off");
        }
	*/
    }

    private BroadcastReceiver mScreenReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();

            if (action.equals(ACTION_SCREEN_ON)) {
                Log.d(TAG, "SCREEN_ON");

                //Remove listener of serial port
                mMtkSerialPort.uninit();

                //Register listener of serial port
                //mMtkSerialPort.init();
                init(intent);
                //After resuming from STR, don't need re-entering the three commands.
                setFactoryMode(Types.FactoryMode.STATE_ACTIVE.ordinal());
            } else if (action.equals(ACTION_SCREEN_OFF)) {
                Log.d(TAG, "SCREEN_OFF");
            }
        }
    };
}
